#!/bin/bash

set -eux

action="$1"
vm="$2"
device="${3-0}"
part="${4-}"

function xe_min() {
  local cmd="$1"
  shift
  xe "$cmd" --minimal "$@"
}

function run_udev_settle() {
  which_udev=$(which udevsettle) || true
  if [ -n "$which_udev" ]; then
      udevsettle
  else
      udevadm settle
  fi
}

vm_uuid=$(xe_min vm-list name-label="$vm")
vdi_uuid=$(xe_min vbd-list params=vdi-uuid vm-uuid="$vm_uuid" \
                           userdevice="$device")

dom0_uuid=$(xe_min vm-list is-control-domain=true)

function get_mount_device() {
  vbd_uuid=$1

  dev=$(xe_min vbd-list params=device uuid="$vbd_uuid")
  if [[ "$dev" =~ "sm/" || "$dev" =~ "blktap-2/" ]]; then
    DEBIAN_FRONTEND=noninteractive \
        apt-get --option "Dpkg::Options::=--force-confold" --assume-yes \
        install kpartx &> /dev/null || true
    mapping=$(kpartx -av "/dev/$dev" | sed -ne 's,^add map \([a-z0-9\-]*\).*$,\1,p' | sed -ne "s,^\(.*${part}\)\$,\1,p")
    if [ -z "$mapping" ]; then
       echo "Failed to find mapping"
       exit -1
    fi

    local device="/dev/mapper/${mapping}"
    for (( i = 0; i < 5; i++ )) ; do
        if [ -b $device ] ; then
            echo $device
            return
        fi
        sleep 1
    done
    echo "ERROR: timed out waiting for dev-mapper"
    exit 1
  else
    echo "/dev/$dev$part"
  fi
}

function clean_dev_mappings() {
  dev=$(xe_min vbd-list params=device uuid="$vbd_uuid")
  if [[ "$dev" =~ "sm/" || "$dev" =~ "blktap-2/" ]]; then
    kpartx -dv "/dev/$dev"
  fi
}

function open_vdi() {
  vbd_uuid=$(xe vbd-create vm-uuid="$dom0_uuid" vdi-uuid="$vdi_uuid" \
                         device=autodetect)
  mp=$(mktemp -d)
  xe vbd-plug uuid="$vbd_uuid"

  run_udev_settle

  mount_device=$(get_mount_device "$vbd_uuid")
  mount "$mount_device" "$mp"
  echo "Your vdi is mounted at $mp"
}

function close_vdi() {
  vbd_uuid=$(xe_min vbd-list vm-uuid="$dom0_uuid" vdi-uuid="$vdi_uuid")
  mount_device=$(get_mount_device "$vbd_uuid")
  run_udev_settle
  umount "$mount_device"

  clean_dev_mappings

  xe vbd-unplug uuid=$vbd_uuid
  xe vbd-destroy uuid=$vbd_uuid
}

if [ "$action" == "open" ]; then
  open_vdi
elif [ "$action" == "close" ]; then
  close_vdi
fi
